/*
 *    Copyright 2022 The DSMS Authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.dsms.dfsbroker.node.api;

import com.dsms.common.remotecall.model.RemoteRequest;
import com.dsms.common.remotecall.model.RemoteResponse;
import com.dsms.dfsbroker.common.CommandDirector;
import com.dsms.dfsbroker.common.api.CommonApi;
import com.dsms.dfsbroker.node.model.remote.OrchDeviceLsResult;
import com.dsms.dfsbroker.node.model.remote.OsdDfResult;
import com.dsms.dfsbroker.node.model.remote.ResponseMon;
import com.dsms.dfsbroker.node.request.RmOsdRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Component
@Slf4j
public class NodeApi {

    public static final int MAX_RETRIES = CommonApi.DEFAULT_RETRY_TIMES;

    private final CommonApi commonApi;

    public NodeApi(CommonApi commonApi) {
        this.commonApi = commonApi;
    }

    /**
     * get dsms-storage node list
     * call /mon api
     *
     * @return /mon response
     */
    public List<ResponseMon> getNodeList(RemoteRequest remoteRequest) throws Throwable {
        CommandDirector.constructMonRequest(remoteRequest);
        ResponseMon[] responseMon = commonApi.remoteCall(remoteRequest, MAX_RETRIES, ResponseMon[].class);
        return Arrays.stream(responseMon).collect(Collectors.toList());
    }

    /**
     * Get a list of discovered devices, grouped by host and optionally filtered to a particular host
     * if hostname is empty ,this method will return all hosts devices.
     */
    public List<OrchDeviceLsResult> getOrchDeviceLs(RemoteRequest remoteRequest, String hostname) throws Throwable {
        CommandDirector.constructOrchDeviceLsRequest(remoteRequest, hostname);
        OrchDeviceLsResult[] orchDeviceLsResults = commonApi.remoteCallRequest(remoteRequest, MAX_RETRIES, OrchDeviceLsResult[].class);
        return Arrays.stream(orchDeviceLsResults).collect(Collectors.toList());

    }

    public OsdDfResult getOsdDf(RemoteRequest remoteRequest) throws Throwable {
        CommandDirector.constructOsdDfRequest(remoteRequest);
        return commonApi.remoteCallRequest(remoteRequest, MAX_RETRIES, OsdDfResult.class);
    }

    public RemoteResponse addOsd(RemoteRequest remoteRequest, String nodeName, String devicePath) throws Throwable {
        CommandDirector.constructAddOsd(remoteRequest, nodeName, devicePath);
        return commonApi.remoteCall(remoteRequest, MAX_RETRIES, RemoteResponse.class);
    }

    public RemoteResponse getAddOsdResult(RemoteRequest remoteRequest, String requestId) throws Throwable {
        CommandDirector.constructGetRequest(remoteRequest, requestId);
        return commonApi.remoteCall(remoteRequest, MAX_RETRIES, RemoteResponse.class);
    }

    public boolean rmOsdSchedule(RemoteRequest remoteRequest, String[] osdId) throws Throwable {
        CommandDirector.constructRmOsd(remoteRequest, osdId);
        String outb = commonApi.remoteCallRequest(remoteRequest, MAX_RETRIES, String.class);
        return Objects.equals(outb, RmOsdRequest.RMOSD_STATUS);
    }


    public RemoteResponse getRmOsdScheduleStatus(RemoteRequest remoteRequest) throws Throwable {
        CommandDirector.constructRmOsdStatus(remoteRequest);
        RemoteResponse remoteResponse = commonApi.remoteCall(remoteRequest, MAX_RETRIES, RemoteResponse.class);
        CommandDirector.constructGetRequest(remoteRequest, remoteResponse.getId());
        return commonApi.remoteCall(remoteRequest, MAX_RETRIES, RemoteResponse.class);
    }

    public RemoteResponse zapOsd(RemoteRequest remoteRequest, String host, String devicePath) throws Throwable {
        CommandDirector.constructZapOsd(remoteRequest, host, devicePath);
        return commonApi.remoteCall(remoteRequest, MAX_RETRIES, RemoteResponse.class);
    }

    public RemoteResponse stopOsd(RemoteRequest remoteRequest, Integer osdId) throws Throwable {
        CommandDirector.constructStopOsd(remoteRequest, osdId);
        return commonApi.remoteCall(remoteRequest, MAX_RETRIES, RemoteResponse.class);
    }

    public RemoteResponse purgeOsd(RemoteRequest remoteRequest, Integer osdId) throws Throwable {
        CommandDirector.constructPurgeOsd(remoteRequest, osdId);
        return commonApi.remoteCall(remoteRequest, MAX_RETRIES, RemoteResponse.class);
    }
}
